package com.ruoyi.accounting.service.impl;

import com.ruoyi.accounting.domain.AccAccount;
import com.ruoyi.accounting.domain.AccAccountingRecord;
import com.ruoyi.accounting.domain.AccClassification;
import com.ruoyi.accounting.domain.dto.AccAccountingRecordImport;
import com.ruoyi.accounting.enums.AccountingRecordTypeEnum;
import com.ruoyi.accounting.service.AccAccountService;
import com.ruoyi.accounting.service.AccClassificationService;
import com.ruoyi.accounting.service.AccountingRecordStrategy;
import com.ruoyi.common.core.enums.DelFlag;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 支出流水策略
 */
@Component
@Slf4j
public class ExpenditureAccountingRecordStrategy implements AccountingRecordStrategy {
    @Autowired
    AccAccountService accAccountService;

    @Autowired
    AccClassificationService accClassificationService;

    @Override
    public void validate(AccAccountingRecord request) {
        if (request.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
            throw new ServiceException("支出金额必须小于0");
        }
        if (request.getSourceAccountId() == null) {
            throw new ServiceException("支出流水必须指定源账户");
        }
    }

    @Override
    public void process(AccAccountingRecord request) {

    }

    @Override
    public Integer getType() {
        return AccountingRecordTypeEnum.EXPENDITURE.getCode();
    }

    @Override
    public List<AccAccountingRecord> importFromExcel(List<AccAccountingRecordImport> importList, Long bookId) {
        if (bookId == null) {
            throw new ServiceException("账本id不能为空");
        }

        //账户
        AccAccount accAccount = new AccAccount();
        accAccount.setAccountBookId(bookId);
        accAccount.setDelFlag(DelFlag.normal.getCode());
        List<AccAccount> accAccounts = accAccountService.selectAccAccountList(accAccount);
        Map<String, Long> accountMap = accAccounts.stream().collect(Collectors.toMap(AccAccount::getAccountName, AccAccount::getId));
        //分类 带层级
        List<AccClassification> classificationList = accClassificationService.selectLevelClassificationList(bookId);
        //map<父级名称，子级集合>
        Map<String, Map<String, Long>> parentToSubNames = classificationList.stream()
                .filter(Objects::nonNull) // 避免空父级
                .collect(Collectors.toMap(
                        AccClassification::getClassificationName,
                        parent -> Optional.ofNullable(parent.getSubClassifications()).orElse(Collections.emptyList())
                                .stream()
                                .filter(Objects::nonNull)
                                .collect(Collectors.toMap(AccClassification::getClassificationName, AccClassification::getId, (existing, replacement) -> existing))));

        Date nowDate = DateUtils.getNowDate();
        String username = SecurityUtils.getUsername();
        ArrayList<AccAccountingRecord> insertRecord = new ArrayList<>(importList.size());
        //校验并填充属性
        for (AccAccountingRecordImport importData : importList) {

            //校验金额
            if (importData.getAmount() == null || importData.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("文件中支出金额必须大于0");
            }

            //校验账户
            if (importData.getAccount() == null || !accountMap.containsKey(importData.getAccount())) {
                throw new ServiceException("账户不存在");
            }

            //校验分类
            if (parentToSubNames.containsKey(importData.getCategory())) {
                if (!parentToSubNames.get(importData.getCategory()).containsKey(importData.getSubCategory())) {
                    throw new ServiceException("子分类不存在");
                }
            } else {
                throw new ServiceException("分类不存在");
            }

            //校验时间
            if (importData.getRecordTime() == null) {
                throw new ServiceException("流水日期不存在");
            }

            AccAccountingRecord record = new AccAccountingRecord();
            record.setAccountBookId(bookId);
            record.setAmount(importData.getAmount());
            record.setSourceAccountId(accountMap.get(importData.getAccount()));
            record.setRecordType(getType());
            record.setClassificationId(parentToSubNames.get(importData.getCategory()).get(importData.getSubCategory()));
            record.setRecordTime(importData.getRecordTime());
            record.setRemark(importData.getRemark());
            record.setCreateTime(nowDate);
            record.setCreateBy(username);
            record.setDelFlag(DelFlag.normal.getCode());
            insertRecord.add(record);
        }

        return insertRecord;
    }
}
